﻿using WebApp.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace WebApp.DAL
{
    public class BaseRepository<T> where T : class
    {

        public WebApp.Models.dbEntities nContext = null;

        public BaseRepository()
        {
            this.nContext = ContextFactory.GetCurrentContext();
        }

        private int getSessionUserid()
        {
            if (System.Web.HttpContext.Current == null || System.Web.HttpContext.Current.Session == null)
            {
                return 0;
            }
            else if (System.Web.HttpContext.Current.Session[WebApp.DAL.ContextFactory.Session_USER_NAME] == null)
            {
                return 0;
            }
            else
            {
                return Convert.ToInt32(System.Web.HttpContext.Current.Session[WebApp.DAL.ContextFactory.Session_USER_ID]);
            }
        }
        private string getSessionUsername()
        {
            if (System.Web.HttpContext.Current == null || System.Web.HttpContext.Current.Session == null)
            {
                return this.getIdentityUsername();
            }
            else if (System.Web.HttpContext.Current.Session[WebApp.DAL.ContextFactory.Session_USER_NAME] == null)
            {
                return this.getIdentityUsername();
            }
            else
            {
                return Utils.NvStr(System.Web.HttpContext.Current.Session[WebApp.DAL.ContextFactory.Session_USER_NAME]);
            }
        }
        private string getIdentityUsername()
        {
            if (System.Web.HttpContext.Current == null || System.Web.HttpContext.Current.User == null)
            {
                return "";
            }
            else
            {
                return System.Web.HttpContext.Current.User.Identity.Name;
            }
        }

        public IQueryable<T> Entities { get { return nContext.Set<T>(); } }

        public T Add(T entity, bool isSave = true)
        {
            PropertyInfo[] props = typeof(T).GetProperties();
            foreach (PropertyInfo p in props)
            {
                if ("Createtime".Equals(p.Name, StringComparison.OrdinalIgnoreCase)
                    || "Createdate".Equals(p.Name, StringComparison.OrdinalIgnoreCase))
                {
                    if (p.PropertyType == typeof(DateTime) || p.PropertyType == typeof(DateTime?))
                    {
                        p.GetSetMethod().Invoke(entity, new object[] { DateTime.Now });
                    }
                }
                else if ("Updatetime".Equals(p.Name, StringComparison.OrdinalIgnoreCase)
                    || "Updatedate".Equals(p.Name, StringComparison.OrdinalIgnoreCase))
                {
                    if (p.PropertyType == typeof(DateTime) || p.PropertyType == typeof(DateTime?))
                    {
                        p.GetSetMethod().Invoke(entity, new object[] { DateTime.Now });
                    }
                }
                else if ("Createuser".Equals(p.Name, StringComparison.OrdinalIgnoreCase)
                   || "Createuserid".Equals(p.Name, StringComparison.OrdinalIgnoreCase))
                {
                    if (p.PropertyType == typeof(int) || p.PropertyType == typeof(int?))
                    {
                        p.GetSetMethod().Invoke(entity, new object[] { this.getSessionUserid() });
                    }
                    else if (p.PropertyType == typeof(string))
                    {
                        p.GetSetMethod().Invoke(entity, new object[] { this.getSessionUsername() });
                    }
                }
                else if ("Updateuser".Equals(p.Name, StringComparison.OrdinalIgnoreCase)
                   || "Updateuserid".Equals(p.Name, StringComparison.OrdinalIgnoreCase))
                {
                    if (p.PropertyType == typeof(int) || p.PropertyType == typeof(int?))
                    {
                        p.GetSetMethod().Invoke(entity, new object[] { this.getSessionUserid() });
                    }
                    else if (p.PropertyType == typeof(string))
                    {
                        p.GetSetMethod().Invoke(entity, new object[] { this.getSessionUsername() });
                    }
                }
            }

            nContext.Set<T>().Add(entity);
            if (isSave) nContext.SaveChanges();
            return entity;
        }

        public int Count()
        {
            return nContext.Set<T>().Count();
        }

        public int Count(Expression<Func<T, bool>> predicate)
        {
            return nContext.Set<T>().Count(predicate);
        }

        public bool Update(T entity, bool isSave = true)
        {
            nContext.Set<T>().Attach(entity);
            nContext.Entry<T>(entity).State = System.Data.Entity.EntityState.Modified;

            PropertyInfo[] props = typeof(T).GetProperties();
            foreach (PropertyInfo p in props)
            {
                if ("Updatetime".Equals(p.Name, StringComparison.OrdinalIgnoreCase)
                    || "Updatedate".Equals(p.Name, StringComparison.OrdinalIgnoreCase))
                {
                    if (p.PropertyType == typeof(DateTime) || p.PropertyType == typeof(DateTime?))
                    {
                        p.GetSetMethod().Invoke(entity, new object[] { DateTime.Now });
                    }
                }
                else if ("Updateuser".Equals(p.Name, StringComparison.OrdinalIgnoreCase)
                   || "Updateuserid".Equals(p.Name, StringComparison.OrdinalIgnoreCase))
                {
                    if (p.PropertyType == typeof(int) || p.PropertyType == typeof(int?))
                    {
                        p.GetSetMethod().Invoke(entity, new object[] { this.getSessionUserid() });
                    }
                    else if (p.PropertyType == typeof(string))
                    {
                        p.GetSetMethod().Invoke(entity, new object[] { this.getSessionUsername() });
                    }
                }
            }

            return isSave ? nContext.SaveChanges() > 0 : true;
        }

        public bool Delete(T entity, bool isSave = true)
        {
            nContext.Set<T>().Attach(entity);
            nContext.Entry<T>(entity).State = System.Data.Entity.EntityState.Deleted;
            return isSave ? nContext.SaveChanges() > 0 : true;
        }

        public bool Exist(Expression<Func<T, bool>> anyLambda)
        {
            return nContext.Set<T>().Any(anyLambda);
        }

        public T Find(int ID)
        {
            return nContext.Set<T>().Find(ID);
        }

        public T Find(Expression<Func<T, bool>> whereLambda)
        {
            T _entity = nContext.Set<T>().FirstOrDefault<T>(whereLambda);
            return _entity;
        }

        public int Save() { return nContext.SaveChanges(); }

        public IQueryable<T> PageList(IQueryable<T> entities, int pageindex, int pagesize)
        {
            return entities.Skip((pageindex - 1) * pagesize).Take(pagesize);
        }
    }
}
